﻿using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using ZCUtil.Singleton;

namespace ZCUIManager
{
    public class UIManager : Singleton<UIManager>
    {
        #region UI
        private Dictionary<eUIType, UIBaseView> m_UISingletonDict;
        private Dictionary<eUIType, GameObject> m_UIPathDict;
        private List<UIBaseView> m_MainViewChildrens;
        private Comparison<UIBaseView> m_Comparison;
        private bool m_UpdateLayer;
        #endregion

        #region uiManagerCanvas
        public RectTransform UICanvasTransform { get; set; }
        public Camera MainCanvasCamera { get; set; }
        public MainCanvasRender MainCanvasRender { get; set; }
        public RectTransform MainCanvasTransform { get; set; }
        #endregion

        #region LiveTime
        public void Initialize()
        {
            m_UISingletonDict = new Dictionary<eUIType, UIBaseView>();
            m_UIPathDict = new Dictionary<eUIType, GameObject>();
            m_MainViewChildrens = new List<UIBaseView>();
            m_Comparison = (a, b) =>
            {
                int diff = a.BigLayer - b.BigLayer;
                return diff == 0 ? a.LayerWeight - b.LayerWeight : -diff;
            };
            m_UpdateLayer = false;
            InitializeUIPathDict();
        }

        public void Tick()
        {
            foreach (UIBaseView view in m_UISingletonDict.Values)
            {
                view.Tick();
            }
            foreach (UIBaseView view in m_MainViewChildrens)
            {
                view.Tick();
            }
            TickUILayer();
        }

        public void Uninitialize()
        {
            m_UISingletonDict.Clear();
            m_UISingletonDict = null;
            m_UIPathDict.Clear();
            m_UIPathDict = null;
        }
        #endregion

        #region 
        public UIBaseView InitializeUI(eUIType uiType)
        {
            m_UISingletonDict.TryGetValue(uiType, out UIBaseView view);
            if (view == null)
            {
                view = CreateView(uiType);
                if (view.isUIView)
                {
                    view.SetParent(UIManager.Instance.UICanvasTransform);
                }
                else
                {
                    view.SetParent(UIManager.Instance.MainCanvasTransform);
                    view.LayerWeight = m_MainViewChildrens.Count;
                    m_MainViewChildrens.Add(view);
                }
                if (view.isSingleton)
                {
                    m_UISingletonDict.Add(uiType, view);
                }
            }
            return view;
        }

        public void UpdateLayer()
        {
            m_UpdateLayer = true;
        }

        public T GetUIView<T>(eUIType uiType) where T : UIBaseView, new()
        {
            UIBaseView view = InitializeUI(uiType);
            if (view != null)
            {
                return view as T;
            }
            Logger.e($"not found uiType is {uiType}.");
            return null;
        }

        public void UninitializeUI(UIBaseView view)
        {
            if (m_UISingletonDict.ContainsKey(view.UIType))
            {
                m_UISingletonDict.Remove(view.UIType);
            }
            view.Uninitialize();
        }
        #endregion

        #region PrivateMethod
        private void InitializeUIPathDict()
        {
            foreach (eUIType uiType in Enum.GetValues(typeof(eUIType)))
            {
                m_UIPathDict.Add(uiType, AssetDatabase.LoadAssetAtPath<GameObject>($"{Const.UIPath}{uiType}.prefab"));
            }
        }

        private UIBaseView CreateView(eUIType uiType)
        {
            m_UIPathDict.TryGetValue(uiType, out GameObject prefabGo);
            GameObject Go = GameObject.Instantiate<GameObject>(prefabGo);
            UIBaseView view = Go.GetComponent<UIBaseView>();
            view.Initialize(uiType, Go);
            view.InitializeListener();
            return view;
        }

        private void TickUILayer()
        {
            if (m_UpdateLayer)
            {
                m_MainViewChildrens.Sort(m_Comparison);
                for (int i = 0; i < m_MainViewChildrens.Count; i++)
                {
                    // m_MainViewChildrens[i].LayerWeight = m_MainViewChildrens.Count - i;
                    m_MainViewChildrens[i].SetSiblingIndex(i);
                }
                m_UpdateLayer = false;
            }
        }
        #endregion
    }
}
